#encoding=utf-8
from utils.ext import inner_db
from werkzeug.security import check_password_hash, generate_password_hash
from marshmallow import Schema, fields, ValidationError, validate, validates_schema
from flask import jsonify, current_app
from flask_jwt import JWT
from datetime import datetime

#运维用户
class Management_User(inner_db.Model):
    __bind_key__ = 'management'
    __tablename__ = 'management_user'
    id = inner_db.Column(inner_db.Integer , primary_key=True, nullable=False, autoincrement=True)
    account = inner_db.Column(inner_db.String(40), unique=True, nullable=False)
    email = inner_db.Column(inner_db.String(40), unique=True, nullable=False)
    password_hash = inner_db.Column(inner_db.String(300), nullable=False)
    role = inner_db.Column(inner_db.String(10))

    # password不可读
    @property
    def password(self):
        raise AttributeError('`password` is not a readable attribute')

    # password加密
    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    # 验证password
    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

    def get_data_info(self):
        return dict(id=self.id, account=self.account, email=self.email, role=self.role)

    def __str__(self):
        return "{}".format(self.get_data_info())

    def __repr__(self):
        return "{}".format(self.get_data_info())

class  ManagementJWT(JWT):
    def __init__(self, app=None):
        def authenticate(username, password):
            user = Management_User.query.filter_by(email=username).first()
            if user and user.verify_password(password):
                return user

        def identity(payload):
            user_id = payload['identity']
            return Management_User.query.get(user_id)

        def auth_response_handler(access_token, identity):
            return jsonify(dict(data=dict(token=access_token.decode('utf-8'),
                                          account = identity.account,
                                          role = identity.role,
                                          message = dict(code = 200,
                                                         status=200,
                                                         message="success"
                                          ))
                                )
                           )

        def payload_handeler(identity):
            iat = datetime.utcnow()
            exp = iat + current_app.config.get('JWT_EXPIRATION_DELTA')
            nbf = iat + current_app.config.get('JWT_NOT_BEFORE_DELTA')
            id = getattr(identity, 'id') or identity['id']
            role = getattr(identity, 'role') or identity['role']
            return {'exp': exp,
                    'iat': iat,
                    'nbf': nbf,
                    'identity': id,
                    'role': role}

        super(ManagementJWT, self).__init__(app=app, authentication_handler=authenticate, identity_handler=identity)
        self.auth_response_handler(auth_response_handler)
        self.jwt_payload_handler(payload_handeler)

class  UserAddSchema(Schema):
    email = fields.String(required=True)
    account = fields.String(required=True)
    password = fields.String(required=True)
    role = fields.String(required=True, validate=validate.OneOf(choices=["admin", "normal"]))

class UserUpdateSchema(Schema):
    email = fields.String(required=True)
    account = fields.String()
    password = fields.String()
    role = fields.String(validate=validate.OneOf(choices=["admin", "normal"]))

class UserDeleteSchema(Schema):
    email = fields.String(required=True)

class TokenManageAddSchema(Schema):
    username = fields.String(required=True)
    password = fields.String(required=True)
